package com.litree.service.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URLDecoder;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Cipher;

import org.apache.catalina.util.URLEncoder;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class CommonUtils {
	 /** 指定加密算法为DESede */
    private static String ALGORITHM = "RSA";
    /** 指定key的大小 */
    private static int KEYSIZE = 2048;
    /** 指定公钥存放文件 */
    private static String PUBLIC_KEY_FILE = "PublicKey";
    /** 指定私钥存放文件 */
    private static String PRIVATE_KEY_FILE = "PrivateKey";

    /**
    * 生成密钥对
    */
    private static void generateKeyPair() throws Exception{
    	File file = new File(getPropertiesBykey("privsteAndPublicKeyPath")+PUBLIC_KEY_FILE);
    	if(!file.exists()){
	      /** RSA算法要求有一个可信任的随机数源 */
	       SecureRandom sr = new SecureRandom();
	       /** 为RSA算法创建一个KeyPairGenerator对象 */
	       KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);
	      /** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
	       kpg.initialize(KEYSIZE, sr);
	       /** 生成密匙对 */
	       KeyPair kp = kpg.generateKeyPair();
	       /** 得到公钥 */
	       Key publicKey = kp.getPublic();
	       /** 得到私钥 */
	       Key privateKey = kp.getPrivate();
	       /** 用对象流将生成的密钥写入文件 */
	       ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream(getPropertiesBykey("privsteAndPublicKeyPath")+PUBLIC_KEY_FILE));
	       ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(getPropertiesBykey("privsteAndPublicKeyPath")+PRIVATE_KEY_FILE));
	       oos1.writeObject(publicKey);
	       oos2.writeObject(privateKey);
	       /** 清空缓存，关闭文件输出流 */
	       oos1.close();
	       oos2.close();
    	}
    }

    /**
    * 加密方法
    * source： 源数据
    */
    public static String encrypt(String source){
    	/** 将文件中的公钥对象读出 */
	       ObjectInputStream ois = null;
    	try{
    		generateKeyPair();
    	   ois = new ObjectInputStream(new FileInputStream(getPropertiesBykey("privsteAndPublicKeyPath")+PUBLIC_KEY_FILE));
	       Key key = (Key) ois.readObject();
	       /** 得到Cipher对象来实现对源数据的RSA加密 */
	       Cipher cipher = Cipher.getInstance(ALGORITHM);
	       cipher.init(Cipher.ENCRYPT_MODE, key);
	       byte[] b = source.getBytes();
	       /** 执行加密操作 */
	       byte[] b1 = cipher.doFinal(b);
	       BASE64Encoder encoder = new BASE64Encoder();
	       URLEncoder ue = new URLEncoder();
	       String urlencode = ue.encode(encoder.encode(b1));
	       return urlencode;
    	}catch(Exception e){
    		System.out.println(e.toString());
    	}finally{
    		try {
    			if(ois !=null){
    				ois.close();    				
    			}
			} catch (IOException e) {
				System.out.println(e.toString());
			}
    	}
		return source;
    }

    /**
    * 解密算法
    * cryptograph:密文
    */
    public static String decrypt(String cryptograph) throws Exception{
       /** 将文件中的私钥对象读出 */
       ObjectInputStream ois = new ObjectInputStream(new FileInputStream(getPropertiesBykey("privsteAndPublicKeyPath")+PRIVATE_KEY_FILE));
       Key key = (Key) ois.readObject();
       ois.close();
       /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
       Cipher cipher = Cipher.getInstance(ALGORITHM);
       cipher.init(Cipher.DECRYPT_MODE, key);
       String decodeCryptograph = URLDecoder.decode(cryptograph);
       BASE64Decoder decoder = new BASE64Decoder();
       byte[] b1 = decoder.decodeBuffer(decodeCryptograph);
       /** 执行解密操作 */
       byte[] b = cipher.doFinal(b1);
       return new String(b);
    }
    
    public static String getPropertiesBykey(String key){
    	String val = "";
    	try {
	    	Resource resource = new ClassPathResource("/message.properties");
			Properties props;
			props = PropertiesLoaderUtils.loadProperties(resource);
			val = (String) props.get(key);
		} catch (IOException e) {
			e.printStackTrace();
		}
    	return val;
    }
    
    /**
     * 设置错误信息
     * @param codeStr
     * @param descStr
     * @param e
     * @return
     */
    public static String errMsg(int codeStr,String descStr,Exception e){
    	return "error code:"+codeStr+",desc:"+descStr+","+"root cause: "+e.toString();
    }

/**
 * check params is legal
 * @param params
 * @return when has risk return false, otherwise true
 */
public static boolean checkParam(String[] params,String checkType) {
	for (String string : params) {
		if(hasCrossScriptRisk(string,getPropertiesBykey(checkType))){
			return false;
		}
	}
	return true;
}

/**
* 检查输入的数据中是否有特殊字符
* @param qString 要检查的数据
* @param regx 特殊字符正则表达式
* @return boolean 如果包含正则表达式 <code> regx </code> 中定义的特殊字符，返回true；
* 否则返回false
*/
public static boolean hasCrossScriptRisk(String qString, String regx) {
	if (qString!=null) {
		qString = qString.trim();
		Pattern p = Pattern.compile(regx, Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(qString);
		return m.find();
	}
	return false;
}

}
